University of Hawaii Sea Level Center (UHSLC) Research Quality Daily

https://uhslc.soest.hawaii.edu/data/?rq

Caldwell, P. C., M. A. Merrifield, P. R. Thompson (2015), Sea level measured by tide gauges from global oceans — the Joint Archive for Sea Level holdings (NCEI Accession 0019568), Version 5.5, NOAA National Centers for Environmental Information, Dataset, doi:10.7289/V5V40S7W.

Permanent Service for Mean Sea Level (PSMSL)

https://psmsl.org

Permanent Service for Mean Sea Level (PSMSL), 2023, "Tide Gauge Data",

Retrieved 24 Apr 2023 from http://www.psmsl.org/data/obtaining/.

Start with imporint the Python libraries. In this instance, we need pandas to work with data and plotly to plot it.

In [1]:
import pandas as pd
import plotly.graph_objs as go
import plotly.express as px

Identify data sources. Each location has three sources: The UHSLC daily, the PSMSL monthly mean, and the PSMSL annual mean.

In [2]:
# Crescent City, PSMSL ID 378
uhslc_cs  = "https://uhslc.soest.hawaii.edu/data/csv/rqds/pacific/daily/d556a.csv"
rlr_mo_cs = "https://psmsl.org/data/obtaining/rlr.monthly.data/378.rlrdata"
rlr_an_cs = "https://psmsl.org/data/obtaining/rlr.annual.data/378.rlrdata"

# San Francisco, GLOSS ID 158, PSMSL ID 10 
uhslc_sf  = "https://uhslc.soest.hawaii.edu/data/csv/rqds/pacific/daily/d551a.csv"
rlr_mo_sf = "https://psmsl.org/data/obtaining/rlr.monthly.data/10.rlrdata"
rlr_an_sf = "https://psmsl.org/data/obtaining/rlr.annual.data/10.rlrdata"

# Los Angeles, PSMSL ID 245
uhslc_la  = "https://uhslc.soest.hawaii.edu/data/csv/rqds/pacific/daily/d567a.csv"
rlr_mo_la = "https://psmsl.org/data/obtaining/rlr.monthly.data/245.rlrdata"
rlr_an_la = "https://psmsl.org/data/obtaining/rlr.annual.data/245.rlrdata"

# San Diego (La Jolla), GLOSS ID 159, PSMSL ID 256 
uhslc_sd  = "https://uhslc.soest.hawaii.edu/data/csv/rqds/pacific/daily/d554a.csv"
rlr_mo_sd = "https://psmsl.org/data/obtaining/rlr.monthly.data/256.rlrdata"
rlr_an_sd = "https://psmsl.org/data/obtaining/rlr.annual.data/256.rlrdata"

# Port Chicago in Suisun Bay, PSMSL ID 2330 
# No hourly data available from UHSLC
rlr_mo_su = "https://psmsl.org/data/obtaining/rlr.monthly.data/2330.rlrdata"
rlr_an_su = "https://psmsl.org/data/obtaining/rlr.annual.data/2330.rlrdata"

Import and plot daily tide gauge data from UHSLC. We'll ignore erroneous readings, which are indicated by -32767 instead of actual value. For each of these we'll convert the independent year, month, and day columns into a single date column.

In [3]:
headers = ["year", "month", "day", "level"]

df_cs = pd.read_csv(uhslc_cs, names=headers, na_values=-32767)
df_cs['date'] = pd.to_datetime(df_cs[['year', 'month', 'day']])

df_sf = pd.read_csv(uhslc_sf, names=headers, na_values=-32767)
df_sf['date'] = pd.to_datetime(df_sf[['year', 'month', 'day']])

df_la = pd.read_csv(uhslc_la, names=headers, na_values=-32767)
df_la['date'] = pd.to_datetime(df_la[['year', 'month', 'day']])

df_sd = pd.read_csv(uhslc_sd, names=headers, na_values=-32767)
df_sd['date'] = pd.to_datetime(df_sd[['year', 'month', 'day']])
In [4]:
fig = go.Figure()
fig.add_trace(go.Scatter(x=df_cs['date'], y=df_cs['level'], mode='lines', name='Crescent City'))
fig.add_trace(go.Scatter(x=df_sf['date'], y=df_sf['level'], mode='lines', name='San Francisco'))
fig.add_trace(go.Scatter(x=df_la['date'], y=df_la['level'], mode='lines', name='Los Angeles'))
fig.add_trace(go.Scatter(x=df_sd['date'], y=df_sd['level'], mode='lines', name='San Diego'))
fig.update_layout(title='Daily Tide Gauge', xaxis_title='Date', yaxis_title='Tide Level above Datum in mm')
fig.show()

Import and plot monlthly mean tide gauge data from PSMSL. We'll ignore erroneous readings, which are indicated by -99999 instead of actual value. Information regarding RLR can be found at: https://psmsl.org/data/obtaining/rlr.php

In [5]:
df_rlr_mo_cs = pd.read_csv(rlr_mo_cs, sep=';', usecols=[0,1], header=None, na_values=-99999)
df_rlr_mo_sf = pd.read_csv(rlr_mo_sf, sep=';', usecols=[0,1], header=None, na_values=-99999)
df_rlr_mo_la = pd.read_csv(rlr_mo_la, sep=';', usecols=[0,1], header=None, na_values=-99999)
df_rlr_mo_sd = pd.read_csv(rlr_mo_sd, sep=';', usecols=[0,1], header=None, na_values=-99999)
df_rlr_mo_su = pd.read_csv(rlr_mo_su, sep=';', usecols=[0,1], header=None, na_values=-99999)
In [6]:
fig = go.Figure()
fig.add_trace(go.Scatter(x=df_rlr_mo_cs[0], y=df_rlr_mo_cs[1], mode='lines', name='Crescent City'))
fig.add_trace(go.Scatter(x=df_rlr_mo_sf[0], y=df_rlr_mo_sf[1], mode='lines', name='San Francisco'))
fig.add_trace(go.Scatter(x=df_rlr_mo_la[0], y=df_rlr_mo_la[1], mode='lines', name='Los Angeles'))
fig.add_trace(go.Scatter(x=df_rlr_mo_sd[0], y=df_rlr_mo_sd[1], mode='lines', name='San Diego'))
fig.add_trace(go.Scatter(x=df_rlr_mo_su[0], y=df_rlr_mo_su[1], mode='lines', name='Suisun Bay'))
fig.update_layout(title='Monthly Mean Tide Gauge', xaxis_title='Date', yaxis_title='Tide Level above RLR in mm')
fig.show()

Import and plot annual mean tide gauge data from PSMSL. We'll ignore erroneous readings, which are indicated by -99999 instead of actual value.

In [7]:
df_rlr_an_cs = pd.read_csv(rlr_an_cs, sep=';', usecols=[0,1], header=None, na_values=-99999)
df_rlr_an_sf = pd.read_csv(rlr_an_sf, sep=';', usecols=[0,1], header=None, na_values=-99999)
df_rlr_an_la = pd.read_csv(rlr_an_la, sep=';', usecols=[0,1], header=None, na_values=-99999)
df_rlr_an_sd = pd.read_csv(rlr_an_sd, sep=';', usecols=[0,1], header=None, na_values=-99999)
df_rlr_an_su = pd.read_csv(rlr_an_su, sep=';', usecols=[0,1], header=None, na_values=-99999)
In [8]:
fig = go.Figure()
fig.add_trace(go.Scatter(x=df_rlr_an_cs[0], y=df_rlr_an_cs[1], mode='lines', name='Crescent City'))
fig.add_trace(go.Scatter(x=df_rlr_an_sf[0], y=df_rlr_an_sf[1], mode='lines', name='San Francisco'))
fig.add_trace(go.Scatter(x=df_rlr_an_la[0], y=df_rlr_an_la[1], mode='lines', name='Los Angeles'))
fig.add_trace(go.Scatter(x=df_rlr_an_sd[0], y=df_rlr_an_sd[1], mode='lines', name='San Diego'))
fig.add_trace(go.Scatter(x=df_rlr_an_su[0], y=df_rlr_an_su[1], mode='lines', name='Suisun Bay'))
fig.update_layout(title='Annual Mean Tide Gauge', xaxis_title='Date', yaxis_title='Tide Level above RLR in mm')
fig.show()

Add a column to each of the annual dataframes to indicate which location the data is from. This will let us differentiate the data after concatinating the dataframes. We'll then go ahead with the concatination. With that, we can generate a new version of the above line graph which will have trend lines.

In [9]:
df_rlr_an_cs[2] = "Crescent City"
df_rlr_an_sf[2] = "San Francisco"
df_rlr_an_la[2] = "Los Angeles"
df_rlr_an_sd[2] = "San Diego"
df_rlr_an_su[2] = "Suisun Bay"

df_rlr_an = pd.concat([df_rlr_an_cs, df_rlr_an_sf, df_rlr_an_la, df_rlr_an_sd, df_rlr_an_su])
In [10]:
fig = px.scatter(df_rlr_an, x=0, y=1, color=2, title='Annual Mean Tide Gauge With Trend Lines', trendline="ols", )
fig.update_layout(xaxis_title="Date", yaxis_title="Tide Level above RLR in mm", legend_title="City")
fig.show()

From the above we can draw the conclusion that sea level along the California coast has generally been rising over the past century. Its interesting to note that the tide levels near Crescent City are infact lowering. A breif Google search reveals that the land around Crescent City is actually rising at a faster rate than the ocean levels, which is the cause of this discrepency. Also of note is that the water within the Bay Area, as measured at Port Chicago, appears to be higher than along the coast but rising at about the same rate as San Francisco.

https://oehha.ca.gov/epic/impacts-physical-systems/sea-level-rise - Discusses the uplift in the Crescent City region.

In [ ]: